/**
 * @Auther: csp1999
 * @Date: 2021/01/18/16:04
 * @Description: 搜索微服务SkuService接口实现类
 */
@Service
public class SkuEsServiceImpl implements SkuEsService {

    @Autowired
    private SkuEsMapper skuEsMapper;

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

//    @Autowired
//    @Qualifier("restHighLevelClient")
//    private RestHighLevelClient client;

    /**
     * 根据条件搜索：多条件搜索
     *
     * @param searchParamMap
     * @return
     */
    @Override
    public Map<String, Object> search(Map<String, String> searchParamMap) {

        // 构建搜索条件：搜索条件构造器
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        if (searchParamMap != null && searchParamMap.size() > 0) {
            // 根据关键词搜索
            String keywords = searchParamMap.get("keywords");

            if (StringUtils.isEmpty(keywords)) {
                keywords = "华为";// 赋值一个keywords默认的值
            }

            // 添加聚合查询操作：相当于sql的分组查询（去重复）--->SELECT category_name FROM `tb_sku` WHERE `name` LIKE '%华为%' GROUP BY category_name
            // 得到分类名称数据集合：
            //              category_name
            //              交换机
            //              手机
            searchQueryBuilder.addAggregation(
                    // AggregationBuilders聚合条件构造器
                    // terms("categoryName")：给列取别名
                    // field("categoryName.keyword")：
                    //      categoryName字段名称
                    //      .keyword便于聚合搜索：term 查询的时候，由于是精准匹配，所以查询的关键字在es上的类型，必须是keyword而不能是text
                    // 如果不加.keyword会出错：Elasticsearch报错：exception [type=search_phase_execution_exception, reason=all shards failed]
                    // size 指定查询结果的数量 默认是10个
                    AggregationBuilders
                            .terms("categoryName")
                            .field("categoryName.keyword")
                            .size(50)
            );

            // 如果关键词不为空，则搜索关键词数据
            if (!StringUtils.isEmpty(keywords)) {
                searchQueryBuilder.withQuery(
                        QueryBuilders.matchPhraseQuery("name", keywords)
                        // 不能使用：QueryBuilders.matchQuery("name", keywords) ，这样会导致：
                        // 搜索华为 ---> 华    为 二字可以拆分查询，而matchPhraseQuery 是不可以拆分的
                );
            }

            // 分页：默认第1页的50条数据
            searchQueryBuilder.withPageable(PageRequest.of(0, 50));
        }

        // 搜索条件构造器构建：NativeSearchQuery
        NativeSearchQuery searchQuery = searchQueryBuilder.build();

        // 执行搜索，获取封装响应数据结果的SearchHits集合
        SearchHits<SkuInfo> searchHits = elasticsearchRestTemplate.search(searchQuery, SkuInfo.class);

        /*
         * 获取聚合后的以categoryName分组的分类名称集合
         * searchHits.getAggregations() 获取的是Aggregations集合
         * get("skuCategoryGroup") 获取指定categoryName域的分类名称集合数据 eg:[手机,家用电器,手机配件]
         * Aggregation ---> StringTerms 转换成子类
         */
        // Terms ：注意这里是巨型踩坑，在ES7之前可以使用StringTerms，但是7之后，如果出现类型转换错误，建议使用Terms替代StringTerms
        Terms terms = searchHits.getAggregations().get("categoryName");
        // 获取分类名称集合
        List<String> categoryList = this.getStringsCategoryList(terms);


        // 对SearchHits集合进行分页封装
        SearchPage<SkuInfo> searchPageFor = SearchHitSupport.searchPageFor(searchHits, searchQuery.getPageable());

        // 总记录数
        long totalElements = searchPageFor.getTotalElements();
        // 总页数
        int totalPages = searchPageFor.getTotalPages();
        // 当前页数
        int currentPage = searchPageFor.getPageable().getPageNumber();
        // 当前页总记录数
        int currentPageRows = searchPageFor.getPageable().getPageSize();

        // 获取所需SkuInfo集合数据内容
        List<SearchHit<SkuInfo>> content = searchPageFor.getContent();

        // 解析并再封装数据
        // 封装一个Map 存储所有数据，并返回
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("totalPage", totalPages);// 总页数
        resultMap.put("total", totalElements);// 总记录数
        resultMap.put("currentPage", currentPage);// 当前页
        resultMap.put("currentPageRows", currentPageRows);// 当前页总记录数
        resultMap.put("categoryList", categoryList);// 商品分类名称数据集合
        resultMap.put("rows", content);// 商品SkuInfo数据集合

        return resultMap;
    }

    /**
     * 从StringTerms中获取分类名称集合categoryList
     **/
    private List<String> getStringsCategoryList(Terms terms) {
        List<String> categoryList = new ArrayList<>();

        if (terms != null) {
            for (Terms.Bucket bucket : terms.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();// 分组的值（分类名称）
                categoryList.add(keyAsString);
            }
        }
        return categoryList;
    }
}
